type
status
date
slug
summary
tags
category
icon
password
在学习 TurtleBot3 时,遇到了一个有趣的现象:打开 Gazebo 模拟环境并配合 RViz2 可视化时,发现机器人的
map 和 base_link 在同一点,但 odom(里程计坐标系)坐标系却偏离了, 按说base_link和odom应该重合才对。
为什么里程计的原点没和机器人基坐标系对齐?这会不会影响导航或定位?这让我有点困惑,于是花时间排查了一下原因。下面分享我的排查过程和发现,希望能帮到同样遇到这个问题的小伙伴。
第一步:检查 TF 变换话题
我首先想到可能是坐标变换(TF)出了问题,于是用命令查看 /tf 话题的信息:bash
输出显示有两个发布者:
- Node name: turtlebot3_diff_drive(负责差分驱动的节点)
- Node name: robot_state_publisher(负责机器人状态发布的节点)
这里我犯了一个小错误:我最初以为一个话题只能有一个发布者。其实,在 ROS 2 中,这只是推荐做法,不是强制规则。尤其是 /tf 话题,它是个特例——TF2 系统会合并所有发布者的变换数据,按照 frame_id、child_frame_id 和时间戳来组织。不同节点可以发布自己负责的部分变换,这反而是鼓励的做法。但这个发现还没直接解决问题,我继续往下查。
第二步:/odom 话题内容
接下来,观察到
/odom 话题发布的初始位置大约是 x ≈ -2.0, y ≈ -0.5。这说明问题可能出在机器人生成时的初始姿态上。我检查了 TurtleBot3 Gazebo 包的启动文件(launch 文件),特别是
spawn_entity.py 中的默认参数:
原因分析:
- Gazebo 世界原点: Gazebo 加载世界地图时,坐标中心默认是
(0,0)。
- 机器人生成过程:默认情况下,Gazebo 会把机器人生成在 (0,0) 位置。但在
spawn_entity.py中,我们通过x_pose和y_pose参数指定了生成位置为 (-2.0, -0.5)。这相当于 Gazebo 先生成机器人,然后瞬间“传送”它到指定点。所以机器人的/odom(由差分驱动节点发布)会从这个指定位置开始计数。所以,初始/odom位置就是 (-2.0, -0.5)
- 为什么不重合:
/map和/base_link以地图原点为参考,而/odom以生成时的偏移位置为起点,导致视觉上不重合。
简单来说,这不是 bug,而是启动配置导致的。如果你想让
/odom 和 /base_link 在启动时重合,可以在启动命令中覆盖参数:这样,
/odom 的初始位置就会接近 (0,0),一切就对齐了。
小结
/odom 和 /base_link 不重合,是因为在 Gazebo 中人为设定了机器人的出生点。机器人虽然出生在 (-2.0, -0.5),但它的里程计坐标系 odom 依然是以它进入世界的那一刻作为参考参考原点的。